In [1]:
%pylab inline
from scipy.integrate import simps


Populating the interactive namespace from numpy and matplotlib

In [2]:
import pyximport; pyximport.install(setup_args={"include_dirs":numpy.get_include()})
import paramless as pmain
import paramless_cython as pm

In [3]:
from JSAnimation.IPython_display import display_animation

Evolution of metabolic investment strategies

Here I test the function simulation framework with the example of section 6 in Dieckmann et al. JTB (2006)

We will evolve a function $x(a)$, where $a \in [0,1]$ (s.t $x(a) > 0 \forall a$ )

Define fitness and mutations

The domain of $x(\cdot)$ is $(0,1)$.


In [4]:
domain = np.arange(0.001, 1.0, 0.01)

Set up the fitness class


In [5]:
class MetabolicFitness(pm.FitnessFunction):
    def __init__(self, c, domain):
        self.c = c
        self.domain = domain
    def get(self, resident, mutant):
        pass

The energy is defined as $E(x) = \int x(a) da$, which for simulation purposes we will compute using simpson's.


In [6]:
def energy(self, surface, domain):
    return simps(surface, domain)

MetabolicFitness.energy = energy

Metabolic efficiency is defined as $e(a, x(a)) = \frac{x(a)}{x(a)+a}$. Then, the total intake of resources is given by $G(x) = \int r(a)e(a, (a)) da$


In [7]:
def resource_density(self, a):
    return 4.0 * (1.0 - a)

def total_intake(self, surface, domain):
    #create a list of pairs x(a) = a for a in domain
    tuples_surface_domain = zip(surface, domain)
    #r(a)*(x(a)/x(a)+a) for all a in domain
    integrand = [self.resource_density(surface_domain[1])*(surface_domain[0]/(surface_domain[0]+surface_domain[1])) for surface_domain in tuples_surface_domain]
    #integrate over domain
    return simps(integrand, domain)

MetabolicFitness.resource_density = resource_density
MetabolicFitness.total_intake = total_intake

With the total intake and the energy we are ready to compute fitness.


In [8]:
def metabolic_fitness(self,resident, mutant = None):
    fitness_resident = self.total_intake(resident, domain) - self.c*self.energy(resident, domain)
    if not mutant is None:
        fitness_mutant = self.total_intake(mutant, domain) - self.c*self.energy(mutant, domain)
        return fitness_resident, fitness_mutant
    else:
        return fitness_resident

MetabolicFitness.get = metabolic_fitness

Let's evolve things

We use the point mutation that does not allow for negative values and conserves energy.


In [9]:
number_of_generations=5000
initial_surface = np.zeros_like(domain)

First with soft mutations


In [10]:
fitness_function = MetabolicFitness(0.5,domain)
mutator = pm.GaussianMutator(0.01,domain,0.02,0.0)
evolver = pm.StandardEvolver(fitness_function,mutator,1e-8)

ans, series = pmain.evolve(initial_surface, evolver,
                     iterations=number_of_generations,
                     return_time_series=True)

In [11]:
plot(domain, ans)


Out[11]:
[<matplotlib.lines.Line2D at 0x7f3ccdd6e290>]

In [12]:
def prediction_investment(a):
    c=0.5
    if resource_density(None,a) > 0.5*a:
        return math.sqrt((a/c)*resource_density(None,a))-a
    return 0.0

In [13]:
target = [prediction_investment(a) for a in domain]

In [14]:
plot(domain, target)
plot(domain, ans)


Out[14]:
[<matplotlib.lines.Line2D at 0x7f3cce04d2d0>]

In [15]:
ani = pmain.create_video_from_time_series(series, target, domain, filename='./metabolic_soft.mp4', approximate_number_of_frames=300, record_every=50)
display_animation(ani)


Out[15]:


Once Loop Reflect

Now with point mutation


In [16]:
number_of_generations=50000

mutator = pm.PointMutator(0.01,0.0)
evolver = pm.StandardEvolver(fitness_function,mutator,1e-8)

ans_stiff, series_stiff = pmain.evolve(initial_surface, evolver,
                     iterations=number_of_generations,
                     return_time_series=True)

In [17]:
plot(domain, target)
plot(domain, ans_stiff)


Out[17]:
[<matplotlib.lines.Line2D at 0x7f3ccdce6510>]

In [18]:
ani_stiff = pmain.create_video_from_time_series(series_stiff, target, domain, filename='./metabolic_hard.mp4', approximate_number_of_frames=100, record_every=1000)
display_animation(ani_stiff)


Out[18]:


Once Loop Reflect

In [ ]: